package com.kyh.controller.api.sys;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.alibaba.fastjson.JSON;
import com.kyh.entity.Arcticle;
import com.kyh.entity.ArcticleLog;
import com.kyh.entity.Item;
import com.kyh.sys.entity.Admin;
import com.kyh.sys.entity.Adminlog;
import com.kyh.sys.entity.Button;
import com.kyh.sys.entity.Col;
import com.kyh.sys.entity.Columns;
import com.kyh.sys.entity.Imgcode;
import com.kyh.sys.entity.Menu;
import com.kyh.sys.entity.Module;
import com.kyh.sys.entity.Role;
import com.kyh.sys.entity.RoleButton;
import com.kyh.sys.entity.RoleMenu;
import com.kyh.sys.entity.Tables;
import com.kyh.vo.R;

@RestController
@RequestMapping("/api/inter")
public class CommonController {
	
	private static final Logger logger = Logger.getLogger(CommonController.class);
	
	@SuppressWarnings("serial")
	public static Map<String, Class<?>> entityMap = new HashMap<String, Class<?>>(){{
		
		put("admin", Admin.class);
		put("adminlog", Adminlog.class);
		put("button", Button.class);
		put("col", Col.class);
		put("imgcode", Imgcode.class);
		put("menu", Menu.class);
		put("module", Module.class);
		put("role", Role.class);
		put("roleButton", RoleButton.class);
		put("roleMenu", RoleMenu.class);
		put("tables", Tables.class);
		put("columns", Columns.class);
		
		put("arcticle", Arcticle.class);
		put("arcticle_log", ArcticleLog.class);
		put("item", Item.class);
	}};
	
	@SuppressWarnings("serial")
	public static Map<String, String> pkMap = new HashMap<String, String>(){{
		
		put("admin", "adminid");
		put("adminlog", "adminlogid");
		put("button", "buttonId");
		put("col", "colId");
		put("dict", "dictId");
		put("imgcode", "imgcodeid");
		put("menu", "menuId");
		put("module", "moduleId");
		put("role", "roleId");
		put("roleButton", "roleButtonId");
		put("roleMenu", "roleMenuId");
		put("tables", "tableCatalog");	
		put("columns", "tableCatalog");
		
		put("arcticle", "id");
		put("arcticle_log", "id");
		put("item", "id");
	}};
	
	
	@PostMapping(value = "/{serviceName}/{serviceMethodName}")
    @ResponseBody
	public Object common(
			@PathVariable String serviceName,
			@PathVariable String serviceMethodName,
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		Map<String, Object> parameterMap = new HashMap<String, Object>();
		Enumeration<String> reqNames = request.getParameterNames();
		for (; reqNames.hasMoreElements();) {
			String name = reqNames.nextElement();
			parameterMap.put(name, request.getParameter(name));
		}
		
		ServletContext sc = request.getServletContext();
		ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
		Object serviceBean = ac1.getBean(serviceName + "Service");
		
		if ("search".equals(serviceMethodName)) {

			Method method;
			try {
				method = serviceBean.getClass().getDeclaredMethod(serviceMethodName, entityMap.get(serviceName));
				
		        method.setAccessible(true);
		        Object obj = method.invoke(serviceBean, JSON.parseObject(JSON.toJSONString(parameterMap), entityMap.get(serviceName)));
//		        Object obj = method.invoke(serviceBean, mapToObject(parameterMap, entityMap.get(serviceName)));
				return obj;
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if ("add".equals(serviceMethodName)) {

			Method method;
			try {
				method = serviceBean.getClass().getDeclaredMethod(serviceMethodName, entityMap.get(serviceName));
		        method.setAccessible(true);
		        Object obj = method.invoke(serviceBean, mapToObject(parameterMap, entityMap.get(serviceName)));
				return obj;
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if ("edit".equals(serviceMethodName)) {

			Method method;
			try {
				method = serviceBean.getClass().getDeclaredMethod(serviceMethodName, entityMap.get(serviceName));
		        method.setAccessible(true);
		        Object obj = method.invoke(serviceBean, mapToObject(parameterMap, entityMap.get(serviceName)));
				return obj;
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if ("deleteTrue".equals(serviceMethodName)) {

			Method method;
			try {
				method = serviceBean.getClass().getDeclaredMethod(serviceMethodName, Long.class);
		        method.setAccessible(true);
		        Object obj = method.invoke(serviceBean, Long.parseLong(parameterMap.get(pkMap.get(serviceName)).toString()));
				return obj;
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if ("deleteFalse".equals(serviceMethodName)) {

			Method method;
			try {
				method = serviceBean.getClass().getDeclaredMethod(serviceMethodName, Long.class);
		        method.setAccessible(true);
		        Object obj = method.invoke(serviceBean, Long.parseLong(parameterMap.get(pkMap.get(serviceName)).toString()));
				return obj;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
        
		return R.error();
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("orderby", "aaa");
		
		Col col = (Col) JSON.parseObject(JSON.toJSONString(map), entityMap.get("col"));
		
		System.out.println(JSON.toJSONString(col));
	}
	
//	//Map转Conf
//	public static Object mapToConf(Map<String, Object> map, Class<?> confClass, Class<?> entityClass) throws Exception {
//	    if (map == null)
//	        return null;
//	    Object obj = confClass.newInstance();
//	    Field[] fields = obj.getClass().getSuperclass().getDeclaredFields();
//	    for (Field field : fields) {
//	        int mod = field.getModifiers();
//	        if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
//	            continue;
//	        }
//	        field.setAccessible(true);
//	        
//	        if (map.containsKey(field.getName())) {
//        	
//	        	Object value = map.get(field.getName());
//	        	if (value != null) {
//	        		if (field.getType() == Integer.class) {
//			            field.set(obj, Integer.parseInt(value.toString()));
//					} else if (field.getType() == Long.class) {
//			            field.set(obj, Long.parseLong(value.toString()));
//					} else if (field.getType() == BigDecimal.class) {
//			            field.set(obj, new BigDecimal(value.toString()));
//					} else if (field.getType() == String.class) {
//			            field.set(obj, value.toString());
//					}
//				}
//			} else if ("e".equals(field.getName())) {
//        		field.set(obj, mapToObject(map, entityClass));
//			} else if ("orderBy".equals(field.getName())) {
//        		field.set(obj, mapToObject(map, OrderBy.class));
//			}
//	    }
//	    return obj;
//	}
	
	//Map转Object
	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) throws Exception {
	    if (map == null)
	        return null;
	    Object obj = beanClass.newInstance();
	    Field[] fields = obj.getClass().getDeclaredFields();
	    for (Field field : fields) {
	        int mod = field.getModifiers();
	        if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
	            continue;
	        }
	        field.setAccessible(true);
	        if (map.containsKey(field.getName())) {
	        	Object value = map.get(field.getName());
	        	if (value != null && value.toString().length() > 0) {
	        		if (field.getType() == Integer.class) {
			            field.set(obj, Integer.parseInt(value.toString()));
					} else if (field.getType() == Long.class) {
			            field.set(obj, Long.parseLong(value.toString()));
					} else if (field.getType() == BigDecimal.class) {
			            field.set(obj, new BigDecimal(value.toString()));
					} else if (field.getType() == String.class) {
			            field.set(obj, value.toString());
					} else if (field.getType() == Boolean.class) {
			            field.set(obj, value.toString());
					}
				}
	        }
	    }
	    return obj;
	}
}
